import { forIn } from "lodash"
import { encryptByMd5 } from "./cipher-plus"
import { getSecretInfo } from "./encrypt-key"
import { useGlobSetting } from "/@/hooks/setting"
import { isArray, isObject } from "/@/utils/is"
const glob = useGlobSetting()
interface SignInfo {
  sign: string
  ts: string
}

export default class SignUtil {
  /**
   * json参数升序
   * @param jsonObj 发送参数
   */

  static sortAsc(jsonObj) {
    if (!isObject(jsonObj) && !isArray(jsonObj)) {
      return jsonObj
    }
    const arr : any[] = []
    let num = 0
    for (const key in jsonObj) {
      arr[num] = key
      num++
    }
    const sortArr = arr.sort()
    const sortObj :any = {}
    for (const i in sortArr) {
      const key = sortArr[i]
      const value = jsonObj[key]
      if (isObject(value)) {
        sortObj[key] = this.sortAsc(value)
      } else if (isArray(value)) {
        num = 0
        sortObj[key] = []
        for (const i2 in value) {
          sortObj[key][num++] = this.sortAsc(value[i2])
        }
      } else {
        sortObj[key] = value
      }
    }
    return sortObj
  }

  /**
   * @param url 请求的url,应该包含请求参数(url的?后面的参数)
   * @param requestParams 请求参数(POST的JSON参数)
   * @returns {string} 获取签名
   */
  static getSign(url, requestParams): SignInfo {
    try {
      const signKey = getSecretInfo()?.signKey
      const urlParams = this.parseQueryString(url)
      const jsonObj = this.mergeObject(requestParams, urlParams)
      const requestBody = this.sortAsc(jsonObj)
      // delete requestBody._t
      const ts = this.getTimestamp()
      const clientId = glob.oauth2ClientId + "_" + glob.oauth2ClientVersion
      const jsonData = JSON.stringify(requestBody, (key, value) => {
        if (value != null && value != undefined && value != "null") {
          if (typeof value !== "object") {
            return value.toString()
          }
          return value
        }
      })

      console.log('signData', jsonData)
      return {
        sign: encryptByMd5(jsonData + clientId + signKey + ts).toLowerCase(),
        ts: ts + "",
      }
    } catch (err) {
      console.log("url", url)
      console.error("生成签名失败", err)
      throw new Error("生成签名失败")
    }
  }

  /**
   * @param url 请求的url
   * @returns {{}} 将url中请求参数组装成json对象(url的?后面的参数)
   */
  static parseQueryString(url) {
    const urlReg = /^[^\?]+\?([\w\W]+)$/,
      paramReg = /([^&=]+)=([\w\W]*?)(&|$|#)/g,
      urlArray = urlReg.exec(url),
      result = {}

    if (urlArray && urlArray[1]) {
      let paramString = urlArray[1],
        paramResult
      while ((paramResult = paramReg.exec(paramString)) != null) {
        //数字值转为string类型，前后端加密规则保持一致
        if (this.myIsNaN(paramResult[2])) {
          paramResult[2] = paramResult[2].toString()
        }
        result[paramResult[1]] = decodeURIComponent(paramResult[2])
      }
    }
    return result
  }

  /**
   * @returns {*} 将两个对象合并成一个
   */
  static mergeObject(objectOne, objectTwo) {
    if (objectTwo && Object.keys(objectTwo).length > 0) {
      for (const key in objectTwo) {
        if (objectTwo.hasOwnProperty(key) === true) {
          //数字值转为string类型，前后端加密规则保持一致
          if (this.myIsNaN(objectTwo[key])) {
            objectTwo[key] = objectTwo[key].toString()
          }
          objectOne[key] = objectTwo[key]
        }
      }
    }
    return objectOne
  }

  static urlEncode(param, key, encode) {
    if (param == null) return ""
    let paramStr = ""
    const t = typeof param
    if (t == "string" || t == "number" || t == "boolean") {
      paramStr += "&" + key + "=" + (encode == null || encode ? encodeURIComponent(param) : param)
    } else {
      for (const i in param) {
        const k = key == null ? i : key + (param instanceof Array ? "[" + i + "]" : "." + i)
        paramStr += this.urlEncode(param[i], k, encode)
      }
    }
    return paramStr
  }

  /**
   * 接口签名用 生成header中的时间戳
   * @returns {number}
   */
  static getTimestamp() {
    return new Date().getTime()
  }

  // static getDateTimeToString() {
  //   const date_ = new Date()
  //   const year = date_.getFullYear()
  //   let month = date_.getMonth() + 1
  //   let day = date_.getDate()
  //   if (month < 10) month = '0' + month
  //   if (day < 10) day = '0' + day
  //   let hours = date_.getHours()
  //   let mins = date_.getMinutes()
  //   let secs = date_.getSeconds()
  //   const msecs = date_.getMilliseconds()
  //   if (hours < 10) hours = '0' + hours
  //   if (mins < 10) mins = '0' + mins
  //   if (secs < 10) secs = '0' + secs
  //   if (msecs < 10) secs = '0' + msecs
  //   return year + '' + month + '' + day + '' + hours + '' + mins + '' + secs
  // }
  // true:数值型的，false：非数值型
  static myIsNaN(value) {
    return typeof value === "number" && !isNaN(value)
  }
}
